package com.kurt.service.impl;

import com.kurt.dto.SysDictDataDTO;
import com.kurt.dto.create.SysDictDataCreateRequest;
import com.kurt.dto.query.SysDictDataQueryRequest;
import com.kurt.dto.update.SysDictDataUpdateRequest;
import com.kurt.entity.SysDictData;
import com.kurt.entity.SysDictType;
import com.kurt.repository.SysDictDataRepository;
import com.kurt.repository.SysDictTypeRepository;
import com.kurt.service.SysDictDataService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 数据字典数据服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysDictDataServiceImpl extends BaseServiceImpl<SysDictData, Long> implements SysDictDataService {

    private final SysDictDataRepository dictDataRepository;
    private final SysDictTypeRepository dictTypeRepository;

    @Override
    protected SysDictDataRepository getRepository() {
        return dictDataRepository;
    }

    @Override
    protected SysDictDataRepository getSpecificationExecutor() {
        return dictDataRepository;
    }

    @Override
    @Transactional
    public SysDictDataDTO createDictData(SysDictDataCreateRequest createRequest) {
        log.info("创建数据字典数据: {}", createRequest.getDictLabel());

        // 检查字典类型是否存在
        Optional<SysDictType> dictTypeOpt = dictTypeRepository.findById(createRequest.getDictTypeId());
        if (dictTypeOpt.isEmpty()) {
            throw new RuntimeException("字典类型不存在");
        }

        // 检查字典值是否已存在
        Optional<SysDictData> existingDataOpt = dictDataRepository.findByDictTypeIdAndDictValue(
                createRequest.getDictTypeId(), createRequest.getDictValue());
        if (existingDataOpt.isPresent()) {
            throw new RuntimeException("字典值已存在");
        }

        // 创建字典数据实体
        SysDictData dictData = new SysDictData();
        BeanUtils.copyProperties(createRequest, dictData);
        dictData.setCreateTime(LocalDateTime.now());
        dictData.setUpdateTime(LocalDateTime.now());
        dictData.setCreateUserId(com.kurt.util.UserContext.getUserId());
        dictData.setUpdateUserId(com.kurt.util.UserContext.getUserId());

        // 保存字典数据
        dictData = dictDataRepository.save(dictData);

        log.info("数据字典数据创建成功: {}", dictData.getDictLabel());
        return convertToSysDictDataDTO(dictData);
    }

    @Override
    @Transactional
    public SysDictDataDTO updateDictData(SysDictDataUpdateRequest updateRequest) {
        log.info("更新数据字典数据: {}", updateRequest.getId());

        // 查找字典数据
        SysDictData dictData = getById(updateRequest.getId());

        // 检查字典类型是否存在
        Optional<SysDictType> dictTypeOpt = dictTypeRepository.findById(updateRequest.getDictTypeId());
        if (dictTypeOpt.isEmpty()) {
            throw new RuntimeException("字典类型不存在");
        }

        // 检查字典值是否已存在（排除自己）
        Optional<SysDictData> existingDataOpt = dictDataRepository.findByDictTypeIdAndDictValue(
                updateRequest.getDictTypeId(), updateRequest.getDictValue());
        if (existingDataOpt.isPresent() && !existingDataOpt.get().getId().equals(updateRequest.getId())) {
            throw new RuntimeException("字典值已存在");
        }

        // 更新字典数据信息
        BeanUtils.copyProperties(updateRequest, dictData, "id", "createTime", "createUserId");
        dictData.setUpdateTime(LocalDateTime.now());
        dictData.setUpdateUserId(com.kurt.util.UserContext.getUserId());

        // 保存字典数据
        dictData = dictDataRepository.save(dictData);

        log.info("数据字典数据更新成功: {}", dictData.getDictLabel());
        return convertToSysDictDataDTO(dictData);
    }

    @Override
    public Page<SysDictDataDTO> getDictDataPage(SysDictDataQueryRequest queryRequest) {
        // 构建分页参数
        Sort sort = Sort.by(Sort.Direction.fromString(queryRequest.getOrderDirection()), queryRequest.getOrderBy());
        Pageable pageable = PageRequest.of(queryRequest.getPageNum() - 1, queryRequest.getPageSize(), sort);

        // 构建查询条件
        Specification<SysDictData> spec = buildDictDataSpecification(queryRequest);

        // 执行分页查询
        Page<SysDictData> dictDataPage = dictDataRepository.findAll(spec, pageable);

        // 转换为DTO
        return dictDataPage.map(this::convertToSysDictDataDTO);
    }

    @Override
    public List<SysDictDataDTO> getDictDataList(SysDictDataQueryRequest queryRequest) {
        // 构建查询条件
        Specification<SysDictData> spec = buildDictDataSpecification(queryRequest);

        // 执行查询
        List<SysDictData> dictDatas = dictDataRepository.findAll(spec);

        // 转换为DTO
        return dictDatas.stream().map(this::convertToSysDictDataDTO).collect(Collectors.toList());
    }

    @Override
    public List<SysDictDataDTO> getDictDataByTypeId(Long dictTypeId) {
        List<SysDictData> dictDatas = dictDataRepository.findByDictTypeIdOrderByDictSort(dictTypeId);
        return dictDatas.stream().map(this::convertToSysDictDataDTO).collect(Collectors.toList());
    }

    @Override
    public List<SysDictDataDTO> getDictDataByType(String dictType) {
        Optional<SysDictType> dictTypeOpt = dictTypeRepository.findByDictType(dictType);
        if (dictTypeOpt.isEmpty()) {
            return new ArrayList<>();
        }
        return getDictDataByTypeId(dictTypeOpt.get().getId());
    }

    @Override
    public List<SysDictDataDTO> getEnabledDictDataByType(String dictType) {
        Optional<SysDictType> dictTypeOpt = dictTypeRepository.findByDictType(dictType);
        if (dictTypeOpt.isEmpty()) {
            return new ArrayList<>();
        }
        List<SysDictData> dictDatas = dictDataRepository.findByDictTypeIdAndStatusOrderByDictSort(dictTypeOpt.get().getId(), 1);
        return dictDatas.stream().map(this::convertToSysDictDataDTO).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public boolean deleteDictDatas(List<Long> ids) {
        log.info("批量删除数据字典数据: {}", ids);

        for (Long id : ids) {
            dictDataRepository.deleteById(id);
        }

        log.info("批量删除数据字典数据成功: {}", ids);
        return true;
    }

    @Override
    @Transactional
    public boolean deleteDictDataByTypeId(Long dictTypeId) {
        log.info("根据字典类型ID删除字典数据: {}", dictTypeId);

        dictDataRepository.deleteByDictTypeId(dictTypeId);

        log.info("根据字典类型ID删除字典数据成功: {}", dictTypeId);
        return true;
    }

    /**
     * 构建数据字典数据查询条件
     */
    private Specification<SysDictData> buildDictDataSpecification(SysDictDataQueryRequest queryRequest) {
        return (root, query, cb) -> {
            List<jakarta.persistence.criteria.Predicate> predicates = new ArrayList<>();

            // 字典类型ID查询
            if (queryRequest.getDictTypeId() != null) {
                predicates.add(cb.equal(root.get("dictTypeId"), queryRequest.getDictTypeId()));
            }

            // 字典标签模糊查询
            if (StringUtils.hasText(queryRequest.getDictLabel())) {
                predicates.add(cb.like(root.get("dictLabel"), "%" + queryRequest.getDictLabel() + "%"));
            }

            // 字典值模糊查询
            if (StringUtils.hasText(queryRequest.getDictValue())) {
                predicates.add(cb.like(root.get("dictValue"), "%" + queryRequest.getDictValue() + "%"));
            }

            // 状态查询
            if (queryRequest.getStatus() != null) {
                predicates.add(cb.equal(root.get("status"), queryRequest.getStatus()));
            }

            // 创建时间范围查询
            if (StringUtils.hasText(queryRequest.getCreateTimeStart())) {
                predicates.add(cb.greaterThanOrEqualTo(root.get("createTime"),
                        LocalDateTime.parse(queryRequest.getCreateTimeStart())));
            }
            if (StringUtils.hasText(queryRequest.getCreateTimeEnd())) {
                predicates.add(cb.lessThanOrEqualTo(root.get("createTime"),
                        LocalDateTime.parse(queryRequest.getCreateTimeEnd())));
            }

            return cb.and(predicates.toArray(new jakarta.persistence.criteria.Predicate[0]));
        };
    }

    /**
     * 转换数据字典数据实体为DTO
     */
    private SysDictDataDTO convertToSysDictDataDTO(SysDictData dictData) {
        SysDictDataDTO dto = new SysDictDataDTO();
        BeanUtils.copyProperties(dictData, dto);

        // 设置状态文本
        if (dictData.getStatus() != null) {
            dto.setStatusText(dictData.getStatus() == 1 ? "启用" : "禁用");
        }

        // 获取字典类型信息
        Optional<SysDictType> dictTypeOpt = dictTypeRepository.findById(dictData.getDictTypeId());
        if (dictTypeOpt.isPresent()) {
            SysDictType dictType = dictTypeOpt.get();
            dto.setDictTypeName(dictType.getDictName());
            dto.setDictType(dictType.getDictType());
        }

        return dto;
    }
}
